import AMapLoader from '@amap/amap-jsapi-loader'
import css from './runtime.less'
import debounce from 'lodash/debounce'
declare global {
  interface Window {
    _AMapSecurityConfig: {
      securityJsCode: string
    }
    AMap: any
  }
}
if (!window._AMapSecurityConfig) {
  window._AMapSecurityConfig = {
    securityJsCode: 'ad82f11741e72bd32683ce710c1062e4'
  }
}

const loadAMap = async (plugins?: string[]) => {
  if (window.AMap) {
    return window.AMap
  }
  return AMapLoader.load({
    key: '567686bca77390b086abdc11e705a46c', //申请好的 Web 端开发者 Key，首次调用 load 时必填
    version: '2.0', //指定要加载的 JS API 的版本，缺省时默认为 1.4.15
    plugins //需要使用的的插件列表，如比例尺'AMap.Scale'，支持添加多个如：['AMap.Scale','...','...']
  })
}

const amapPromise = loadAMap()

const loadPlaceSearch = async () => {
  const AMap = await amapPromise
  return new Promise((resolve) => AMap.plugin(['AMap.PlaceSearch', 'AMap.AutoComplete', 'AMap.Geocoder'], resolve))
}

const placeSearchPromise = loadPlaceSearch()

const sleep = (interval = 500) => new Promise((resolve) => setTimeout(resolve, interval))

export interface ValueType {
  lng: number
  lat: number
  address: string
  addressName: string
  province: string
  city: string
  citycode: string
  adname: string
  adcode: string
}

export class PositionPickerRneder {
  private container?: HTMLElement | null
  private autoinputDom?: HTMLElement | null
  private running = true
  private renderIndex = 0
  private map: any = null
  private marker: any = null
  private infownd: any = null
  private infoContent?: HTMLElement | null
  private placeSearch?: any = null
  private address: string = ''
  private center: [number, number] = [116.397428, 39.90923]
  private disabled = false
  private inDesigner = true
  public search: (input: string) => void
  // { addressName, address,  pname: province, cityname: city, citycode, adname, adcode }
  public onChange?: (value: ValueType) => void

  constructor(disabled: boolean = false, inDesigner = true) {
    this.disabled = disabled
    this.inDesigner = inDesigner
    this.search = debounce((input: string) => {
      console.log('real search:', input)
      if (input) this.placeSearch?.search?.(input)
    }, 800)
  }

  private clear() {
    this.map?.destroy()
    this.map = null
  }

  public setCenter(center: [number, number]) {
    this.center = center
    this.map?.setCenter?.(center)
    this.marker?.setPosition?.(center)
    this.map?.add?.(this.marker)
    this.infownd?.open?.(this.map, this.center)
  }

  public setAddress(address: string) {
    this.address = address
    if (this.infoContent) {
      this.infoContent.innerText = address
    }
  }

  setContainer(container?: HTMLElement | null, autoinputDom?: HTMLElement | null) {
    this.container = container
    this.autoinputDom = autoinputDom
  }

  destory() {
    this.running = false
    this.clear()
  }

  clearMap() {
    this.map?.clearMap?.()
  }

  private async initSearchInput() {
    if (!this.map || !this.autoinputDom) return
    const AMap = await amapPromise
    await placeSearchPromise

    const auto = new AMap.AutoComplete({
      input: this.autoinputDom
    })

    const placeSearch = new AMap.PlaceSearch({
      map: this.map
    })
    this.placeSearch = placeSearch
    placeSearch.on('markerClick', (evt: any) => {
      this.map?.clearMap?.()
      const { name: addressName, address, pname: province, cityname: city, citycode, adname, adcode } = evt.data
      this.setAddress(address)
      const { lng, lat } = evt.data.location
      this.setCenter([lng, lat])
      this.onChange?.({ lng, lat, address, addressName, province, city, citycode, adname, adcode })
    })
    auto.on('select', (e: any) => {
      placeSearch.setCity(e.poi.adcode)
      placeSearch.search(e.poi.name)
    })
  }

  private async initInfowdn() {
    if (!this.map) return
    const AMap = await amapPromise
    this.infoContent = document.createElement('div')
    this.infoContent.classList.add(css['info'])
    this.infoContent.innerText = this.address || '这是地址文本'
    this.infownd = new AMap.InfoWindow({
      content: this.infoContent, //传入字符串拼接的 DOM 元素
      isCustom: true,
      offset: [0, -40],
      anchor: 'bottom-center'
    })
    if (this.inDesigner || this.address) {
      this.infownd.open(this.map, this.center)
    }
  }

  private async initMarker() {
    if (!this.map) return
    const AMap = await amapPromise
    this.marker = new AMap.Marker({
      position: this.center
    })
    if (this.inDesigner || this.address) {
      this.map?.add?.(this.marker)
    }
  }

  private async initMap() {
    const AMap = await amapPromise
    if (!AMap) return
    this.map = new AMap.Map(this.container, {
      viewMode: '3D', // 是否为3D地图模式
      zoom: 11, // 初始化地图级别
      center: this.center // 初始化地图中心点位置
    })
    await placeSearchPromise
    const geocoder = new AMap.Geocoder({
      radius: 1000 //范围，默认：500
    })
    if (!this.disabled) {
      this.map.on('click', (e: any) => {
        const { lng, lat } = e.lnglat
        this.setCenter([lng, lat])
        geocoder.getAddress(e.lnglat, (status: any, result: any) => {
          if (status === 'complete' && result.regeocode) {
            const address = result.regeocode.formattedAddress
            // const { addressName, address,  pname: province, cityname: city, citycode, adname, adcode }
            const { province, city, citycode, district: adname, adcode, township: addressName } = result.regeocode.addressComponent
            this.setAddress(address)
            this.onChange?.({ lng, lat, address, addressName, province, city, citycode, adname, adcode })
          } else {
            console.error('根据经纬度查询地址失败')
          }
        })
      })
    }
  }

  async render() {
    this.renderIndex++
    const idx = this.renderIndex
    this.running = true

    await sleep()

    if (idx != this.renderIndex) return
    if (!this.running) return
    if (!this.container) return

    this.clear()
    await this.initMap()
    await this.initMarker()
    await this.initInfowdn()
    await this.initSearchInput()
    console.log('render finish', idx)
  }
}
